#include "Generate_C_std.h"

/*
 * OOP Field access
 */

class Pattern_assign_field : public Pattern
{
public:
	bool match(Statement* that)
	{
		pattern = new Wildcard<Assign_field>;
		return that->match(pattern);
	}

	void generate_code(Generate_C* gen)
	{
		VARIABLE_NAME* object_name;
		CLASS_NAME* class_name;
		FIELD_NAME* field_name;
		Variable_field* var_field;
 		
		object_name = dynamic_cast<VARIABLE_NAME*>(pattern->value->target);
 		class_name  = dynamic_cast<CLASS_NAME*>(pattern->value->target);
		field_name  = dynamic_cast<FIELD_NAME*>(pattern->value->field_name);
		var_field   = dynamic_cast<Variable_field*>(pattern->value->field_name);

		bool is_ref = pattern->value->is_ref;
		Rvalue* rhs = pattern->value->rhs;

		if (field_name != NULL)
		{
			if (object_name != NULL)
			{
				if (!is_ref)
					INST (buf, "assign_field", object_name, field_name, rhs);
				else
					INST (buf, "assign_field_ref", object_name, field_name, rhs);
			}
			else if (class_name != NULL)
			{
				if (!is_ref)
					INST (buf, "assign_static_field", class_name, field_name, rhs);
				else
					INST (buf, "assign_static_field_ref", class_name, field_name, rhs);
			}
			else
			{
				// Invalid target
				phc_unreachable();
			}
		}
		else if (var_field != NULL)
		{
			VARIABLE_NAME* var_field_name = var_field->variable_name;

			if (object_name != NULL)
			{
				if (!is_ref)
					INST (buf, "assign_var_field", object_name, var_field_name, rhs);
				else
					INST (buf, "assign_var_field_ref", object_name, var_field_name, rhs);
			}
			else if (class_name != NULL)
			{
				if (!is_ref)
					INST (buf, "assign_var_static_field", class_name, var_field_name, rhs);
				else
					INST (buf, "assign_var_static_field_ref", class_name, var_field_name, rhs);
			}
			else
			{
				// Invalid target
				phc_unreachable();
			}
		}
		else
		{
			// Invalid field name
			phc_unreachable();
		}
	}

protected:
	Wildcard<Assign_field>* pattern;
};

CREATE(Pattern_assign_field)
